#!/usr/bin/python

import sys
import os
import struct
import socket
import subprocess
import signal
from gi.repository import GLib
from gi.repository import LightDM

display = os.getenv ('DISPLAY');
xdg_seat = os.getenv ('XDG_SEAT');
xdg_vtnr = os.getenv ('XDG_VTNR');
xdg_session_cookie = os.getenv ('XDG_SESSION_COOKIE');
xdg_session_class = os.getenv ('XDG_SESSION_CLASS');
if display is not None:
    if display.startswith (':'):
        greeter_id = 'GREETER-X-%s' % display[1:]
    else:
        greeter_id = 'GREETER-X-%s' % display
else:
    greeter_id = 'GREETER-?'

loop = GLib.MainLoop ()

def sigterm_cb (data):
    status_notify ('%s TERMINATE SIGNAL=%d' % (greeter_id, signal.SIGTERM))
    loop.quit ()
GLib.unix_signal_add (GLib.PRIORITY_DEFAULT, signal.SIGTERM, sigterm_cb, None)

status_socket = None

def status_notify (message):
    if status_socket is not None:
        status_socket.send (struct.pack ('i', len (message)) + message)
    else:
        sys.stderr.write ('%s\n' % message)

def request_cb (channel, condition):
    length = status_socket.recv (4)
    if len (length) == 0:
        loop.quit ();
        return False
    if len (length) > 0:
        (l,) = struct.unpack ('i', length)
        request = status_socket.recv (l)

    r = '%s AUTHENTICATE' % greeter_id
    if request == r:
        greeter.authenticate (None)

    r = '%s AUTHENTICATE USERNAME=' % greeter_id
    if request.startswith (r):
        greeter.authenticate (request[len(r):])

    r = '%s AUTHENTICATE-GUEST' % greeter_id
    if request == r:
        greeter.authenticate_as_guest ()

    r = '%s AUTHENTICATE-AUTOLOGIN' % greeter_id
    if request == r:
        greeter.authenticate_autologin ()

    r = '%s AUTHENTICATE-REMOTE SESSION=' % greeter_id
    if request.startswith (r):
        greeter.authenticate_remote (request[len(r):], None)

    r = '%s RESPOND TEXT=\"' % greeter_id
    if request.startswith (r):
        greeter.respond (request[len (r):-1])

    r = '%s CANCEL-AUTHENTICATION' % greeter_id
    if request == r:
        greeter.cancel_authentication ()

    r = '%s START-SESSION' % greeter_id
    if request == r:
        try:
            greeter.start_session_sync (None)
        except GLib.Error as e:
            status_notify ('%s SESSION-FAILED ERROR=%s' % (greeter_id, e.message))

    r = '%s START-SESSION SESSION=' % greeter_id
    if request.startswith (r):
        try:
            greeter.start_session_sync (request[len(r):])
        except GLib.Error as e:
            status_notify ('%s SESSION-FAILED ERROR=%s' % (greeter_id, e.message))

    r = '%s LOG-USER-LIST-LENGTH' % greeter_id
    if request == r:
        status_notify ('%s LOG-USER-LIST-LENGTH N=%d' % (greeter_id, LightDM.UserList.get_instance ().get_length ()))

    r = '%s LOG-USER USERNAME=' % greeter_id
    if request.startswith (r):
        username = request[len(r):]
        user = LightDM.UserList.get_instance ().get_user_by_name (username)
        status_notify ('%s LOG-USER USERNAME=%s' % (greeter_id, user.get_name ()))

    r = '%s LOG-USER-LIST' % greeter_id
    if request == r:
        users = LightDM.UserList.get_instance ().get_users ();
        for user in users:
            status_notify ('%s LOG-USER USERNAME=%s' % (greeter_id, user.get_name ()))

    r = '%s LOG-SESSIONS' % greeter_id
    if request == r:
        sessions = LightDM.get_sessions ();
        def compare_session (a, b):
            if a.get_key () > b.get_key ():
                return 1
            elif a.get_key () < b.get_key ():
                return -1
            else:
                return 0
        sessions.sort (compare_session)
        for session in sessions:
            status_notify ('%s LOG-SESSION KEY=%s' % (greeter_id, session.get_key ()))

    r = '%s LOG-LAYOUT' % greeter_id
    if request == r:
        layout = LightDM.get_layout ().get_name ()
        status_notify ('%s LOG-LAYOUT LAYOUT=%s' % (greeter_id, layout))

    r = '%s LOG-LAYOUT USERNAME=' % greeter_id
    if request.startswith (r):
        username = request[len(r):]
        user = LightDM.UserList.get_instance ().get_user_by_name (username)
        layout = user.get_layout ()
        if layout is None:
            layout = ''
        status_notify ('%s LOG-LAYOUT USERNAME=%s LAYOUT=%s' % (greeter_id, username, layout))

    r = '%s LOG-LANGUAGE USERNAME=' % greeter_id
    if request.startswith (r):
        username = request[len(r):]
        user = LightDM.UserList.get_instance ().get_user_by_name (username)
        language = user.get_language ()
        if language is None:
            language = ''
        status_notify ('%s LOG-LANGUAGE USERNAME=%s LANGUAGE=%s' % (greeter_id, username, language))

    r = '%s GET-CAN-SUSPEND' % greeter_id
    if request == r:
        if LightDM.get_can_suspend ():
            allowed = "TRUE"
        else:
            allowed = "FALSE"
        status_notify ('%s CAN-SUSPEND ALLOWED=%s' % (greeter_id, allowed))

    r = '%s SUSPEND' % greeter_id
    if request == r:
        try:
            LightDM.suspend ()
        except:
            status_notify ('%s FAIL-SUSPEND' % greeter_id)

    r = '%s GET-CAN-HIBERNATE' % greeter_id
    if request == r:
        if LightDM.get_can_hibernate ():
            allowed = "TRUE"
        else:
            allowed = "FALSE"
        status_notify ('%s CAN-HIBERNATE ALLOWED=%s' % (greeter_id, allowed))

    r = '%s HIBERNATE' % greeter_id
    if request == r:
        try:
            LightDM.hibernate ()
        except:
            status_notify ('%s FAIL-HIBERNATE' % greeter_id)

    r = '%s GET-CAN-RESTART' % greeter_id
    if request == r:
        if LightDM.get_can_restart ():
            allowed = "TRUE"
        else:
            allowed = "FALSE"
        status_notify ('%s CAN-RESTART ALLOWED=%s' % (greeter_id, allowed))

    r = '%s RESTART' % greeter_id
    if request == r:
        try:
            LightDM.restart ()
        except:
            status_notify ('%s FAIL-RESTART' % greeter_id)

    r = '%s GET-CAN-SHUTDOWN' % greeter_id
    if request == r:
        if LightDM.get_can_shutdown ():
            allowed = "TRUE"
        else:
            allowed = "FALSE"
        status_notify ('%s CAN-SHUTDOWN ALLOWED=%s' % (greeter_id, allowed))

    r = '%s SHUTDOWN' % greeter_id
    if request == r:
        try:
            LightDM.shutdown ()
        except:
            status_notify ('%s FAIL-SHUTDOWN' % greeter_id)

    return True

def notify_hints (greeter):
    if greeter.get_select_user_hint () is not None:
        status_notify ('%s SELECT-USER-HINT USERNAME=%s' % (greeter_id, greeter.get_select_user_hint ()))
    if greeter.get_select_guest_hint ():
        status_notify ('%s SELECT-GUEST-HINT' % greeter_id)
    if greeter.get_lock_hint ():
        status_notify ('%s LOCK-HINT' % greeter_id)
    if not greeter.get_has_guest_account_hint ():
        status_notify ('%s HAS-GUEST-ACCOUNT-HINT=FALSE' % greeter_id)
    if greeter.get_hide_users_hint ():
        status_notify ('%s HIDE-USERS-HINT' % greeter_id)
    if greeter.get_show_manual_login_hint ():
        status_notify ('%s SHOW-MANUAL-LOGIN-HINT' % greeter_id)
    if not greeter.get_show_remote_login_hint ():
        status_notify ('%s SHOW-REMOTE-LOGIN-HINT=FALSE' % greeter_id)
    if greeter.get_autologin_user_hint () is not None:
        status_notify ('%s AUTOLOGIN-USER-HINT=%s' % (greeter_id, greeter.get_autologin_user_hint ()))
    if greeter.get_autologin_session_hint () is not None:
        status_notify ('%s AUTOLOGIN-SESSION-HINT=%s' % (greeter_id, greeter.get_autologin_session_hint ()))
    if greeter.get_autologin_guest_hint ():
        status_notify ('%s AUTOLOGIN-GUEST-HINT' % greeter_id)
    if greeter.get_autologin_timeout_hint () != 0:
        status_notify ('%s AUTOLOGIN-TIMEOUT-HINT=%s' % (greeter_id, greeter.get_autologin_timeout_hint ()))

path = os.getenv ('LIGHTDM_TEST_ROOT') + '/.s'
status_socket = socket.socket (socket.AF_UNIX, socket.SOCK_STREAM)
status_socket.connect (path)
GLib.io_add_watch (status_socket.fileno (), GLib.IO_IN | GLib.IO_HUP, request_cb)

status_text = '%s START' % greeter_id
if xdg_seat is not None:
    status_text += ' XDG_SEAT=%s' % xdg_seat
if xdg_vtnr is not None:
    status_text += ' XDG_VTNR=%s' % xdg_vtnr
if xdg_session_cookie is not None:
    status_text += ' XDG_SESSION_COOKIE=%s' % xdg_session_cookie
if xdg_session_class is not None:
    status_text += ' XDG_SESSION_CLASS=%s' % xdg_session_class
status_notify (status_text)

config = GLib.KeyFile ()
config.load_from_file (os.getenv ('LIGHTDM_TEST_ROOT') + '/script', GLib.KeyFileFlags.NONE)

# NOTE: There don't seem to be any good X bindings so we have to mock up our own...
if display is not None:
    (host, display_number) = display.split (':')
    if host == '':
        x_socket = socket.socket (socket.AF_UNIX, socket.SOCK_STREAM)
        x_socket.connect (os.getenv ('LIGHTDM_TEST_ROOT') + '/.x' + display)
    else:
        x_socket = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
        x_socket.connect ((host, 6000 + int (display_number)))

    status_notify ('%s CONNECT-XSERVER' % (greeter_id))

def show_message_cb (greeter, text, type):
    status_notify ('%s SHOW-MESSAGE TEXT=\"%s\"' % (greeter_id, text))

def show_prompt_cb (greeter, text, type):
    status_notify ('%s SHOW-PROMPT TEXT=\"%s\"' % (greeter_id, text))

def authentication_complete_cb (greeter):
    if greeter.get_is_authenticated ():
        is_authenticated = 'TRUE'
    else:
        is_authenticated = 'FALSE'
    if greeter.get_authentication_user () is not None:
        status_notify ('%s AUTHENTICATION-COMPLETE USERNAME=%s AUTHENTICATED=%s' % (greeter_id, greeter.get_authentication_user (), is_authenticated))
    else:
        status_notify ('%s AUTHENTICATION-COMPLETE AUTHENTICATED=%s' % (greeter_id, is_authenticated))

def autologin_timer_expired_cb (greeter):
    pass

greeter = LightDM.Greeter ()
greeter.connect ('show-message', show_message_cb)
greeter.connect ('show-prompt', show_prompt_cb)
greeter.connect ('authentication-complete', authentication_complete_cb)
greeter.connect ('autologin-timer-expired', autologin_timer_expired_cb)
resettable = False
try:
    resettable = config.get_boolean ('test-greeter-config', 'resettable')
except:
    pass
if resettable:
    LightDM.Greeter.get_instance ().set_resettable (True)
    LightDM.Greeter.get_instance ().connect ('idle', idle_cb)
    LightDM.Greeter.get_instance ().connect ('reset', reset_cb)

def user_added_cb (user_list, user):
    status_notify ('%s USER-ADDED USERNAME=%s' % (greeter_id, user.get_name ()))
def user_removed_cb (user_list, user):
    status_notify ('%s USER-REMOVED USERNAME=%s' % (greeter_id, user.get_name ()))
log_user_changes = False
try:
    log_user_changes = config.get_boolean ('test-greeter-config', 'log-user-changes')
except:
    pass
if log_user_changes:
    LightDM.UserList.get_instance ().connect ('user-added', user_added_cb)
    LightDM.UserList.get_instance ().connect ('user-removed', user_removed_cb)

status_notify ('%s CONNECT-TO-DAEMON' % greeter_id)
try:
    greeter.connect_to_daemon_sync ()
except:
    status_notify ('%s FAIL-CONNECT-DAEMON' % greeter_id)
    exit (1)

status_notify ('%s CONNECTED-TO-DAEMON' % greeter_id)

def idle_cb (greeter):
    status_notify ('%s IDLE' % (greeter_id))
def reset_cb (greeter):
    status_notify ('%s RESET' % (greeter_id))
    notify_hints (greeter)

notify_hints (greeter)

loop.run ()
